package syncagent;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;

import syncagent.SyncAgentService;
import syncagent.impl.SyncAgentServiceImpl;

public class SyncAgent implements BundleActivator {
		private ServiceRegistration reg;
		private ServiceTracker tracker;
	 	private Map<SyncAgentService, String> agents = new ConcurrentHashMap<SyncAgentService, String>();
	 	private SyncAgentService localSyncAgent;
	 	
		public void start(BundleContext context) {
	
			// Register service as a distributed OSGi service
			Dictionary props = new Hashtable();
	        
	        String host = getHostName(); // obtain the current host name
	        int port = 0;
			try {
				port = getPort();
			} catch (IOException e) {
				System.out.println("SyncAgent: Unable to get port");
			}        // find a free port
	        
	        props.put("service.exported.interfaces", "*");
	        props.put("service.exported.configs", "org.apache.cxf.ws");
	        props.put("org.apache.cxf.ws.address", "http://" + host + ":" + port + "/display");

			localSyncAgent = new SyncAgentServiceImpl(this);
			reg = context.registerService(SyncAgentService.class.getName(), localSyncAgent, props);
			// Register Event Handler to receive event from Event Admin
			context.registerService(EventHandler.class.getName(),  
									new SyncAgentEventHandler(localSyncAgent),  
									getHandlerServiceProperties("org/dynamicjava/test1"));
			
			// Get instances of remote OSGi SyncAgent Services
			tracker = new ServiceTracker(context, SyncAgentService.class.getName(), null) {
	            public Object addingService(ServiceReference reference) {
	                Object svc = super.addingService(reference);
	                if (svc instanceof SyncAgentService) {
	                	SyncAgentService d = (SyncAgentService) svc;
	                    System.out.println("Adding agent: " + d.getID() + " (" + d + ")");
	                    agents.put(d, d.getID());
	                }
	                return svc;
	            }

	            public void removedService(ServiceReference reference, Object service) {
	                String value = agents.remove(service);
	                System.out.println("Removed agent: " + value);
	                super.removedService(reference, service);
	            }            
	        };        
	        tracker.open();

		}

		public void stop(BundleContext context) {
			reg.unregister();
		}

		public Map<SyncAgentService, String> getClients() {
			return agents;
		}
		
		protected Dictionary getHandlerServiceProperties(String... topics) {  
			Dictionary result = new Hashtable();  
			result.put(EventConstants.EVENT_TOPIC, topics);  
			return result;  
		}  
		
		private static String getAddress(String host, int port) throws Exception {        
	        return "http://" + host + ":" + port + "/display";
	    }

	    private static String getHostName() {
	        try {
	            return InetAddress.getLocalHost().getCanonicalHostName();
	        } catch (UnknownHostException e) {
	            return "localhost";
	        }
	    }

		
	    private static int getPort() throws IOException {
	        return new ServerSocket(0).getLocalPort();
	    }
}